#include <sys_config.h>
#include <sys_parameters.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>

#include <hld/hld_dev.h>
    
#include <api/libsubt/lib_subt.h>
#include <api/libsubt/subt_osd.h>
#include <hld/sdec/sdec.h>

#include <hld/osd/osddrv_dev.h>
#include <hld/osd/osddrv.h>

#include "lib_atsc_subt.h"
#include "lib_subt_atsc_osd.h"

//#define SUBT_ATSC_OSD_PRINTF libc_printf
#define SUBT_ATSC_OSD_PRINTF(...)
//#define tnntc_debug
//BOOL shifty_subt_auto = FALSE;
extern struct OSDRect g_subt_atsc_rect;

extern struct subt_config_par g_subt_config_par;

extern UINT16 globeWidthReal;
extern UINT16 globeHeightReal;
static BOOL bCenter = FALSE;
static BOOL user_force = FALSE;
static INT32 shifty_dcii_subt = 0;
static BOOL bColorExchange = FALSE;
static UINT8 charY = 0xeb;
static UINT8 charCb = 0x80;
static UINT8 charCr = 0x80;
static UINT8 charK = 0xF;
static UINT8 outlineY = 0x16;
static UINT8 outlineCb = 0x80;
static UINT8 outlineCr = 0x80;
static UINT8 outlineK = 0xF;
struct osd_device* lib_subt_atsc_get_osd_handle(void)
{
		#ifdef SHOW_BY_CPU
    		struct osd_device* ret = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, 1);
		#else
	struct osd_device* ret = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, g_subt_config_par.osd_layer_id);
		#endif
    	//struct osd_device* ret = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, 0);
    return ret;
}
#if 0
RET_CODE lib_subt_atsc_get_region_pos(struct osd_device *subt_atsc_osd_dev)
{ 
    RET_CODE ret = SUCCESS;
    struct OSDRect rect;
   ret = OSDDrv_GetRegionPos((HANDLE)subt_atsc_osd_dev,0,&rect);
   if(SUCCESS != ret)
   {
    SDBBP();
   }
   #ifdef tnntc_debug
   
   libc_printf("Character rect region got: uLeft:%d, uTop:%d, uWidth:%d, uHeight:%d\n",rect.uLeft,rect.uTop,\
                   rect.uWidth,rect.uHeight); 
   #endif
   return ret;
}
#endif
extern BOOL osd_region_deleted;
extern UINT8 osd_status;
RET_CODE lib_subt_atsc_create_region(struct osd_device *subt_atsc_osd_dev,struct OSDRect *rect, DISPLAY_STANDARD_TYPE type)
{
    enum OSDSys  eOSDSys = NTSC;
    RET_CODE ret = SUCCESS;
    UINT16 amendHeightReal;
//    return ret;
    switch(type)
    {
        default:
            break;
        case TYPE_720_576_25:
            break;
        case TYPE_720_480_30:	
	    case TYPE_1280_720_60:
	    case TYPE_1920_1080_60:
            eOSDSys = PAL;
    }
//    eOSDSys = PAL;
    do{
        //SUBT_ATSC_OSD_PRINTF("__%d__ l %d t%d w %d h %d\n",__LINE__,rect->uLeft,rect->uTop,rect->uWidth,rect->uHeight);
        if(bCenter)
        {
            amendHeightReal = globeHeightReal+0xf;
        	if(shifty_dcii_subt>0)
        	     rect->uTop = rect->uTop+shifty_dcii_subt;
            #if 1
        	if(FALSE == user_force)
        	{
        	   if(rect->uTop+amendHeightReal>=576)
        	   	    rect->uTop = 576-amendHeightReal;
        	}
        	else
        	{ 
        	   rect->uTop = rect->uTop;
        	}
            #endif
        }
        ret = OSDDrv_CreateRegion((HANDLE)subt_atsc_osd_dev,0,rect,NULL);
        if(SUCCESS != ret)
            break;
        osd_status = 1;
        osd_region_deleted = FALSE;
        ret = OSDDrv_Scale((HANDLE)subt_atsc_osd_dev,OSD_VSCALE_TTX_SUBT,(UINT32)&eOSDSys);
        if(SUCCESS != ret)
           break;
        
        ret = OSDDrv_ShowOnOff((HANDLE)subt_atsc_osd_dev,OSDDRV_ON);
        if(SUCCESS != ret)
            break;
    }while(0);
    return ret;   
}

//Clear OSD Display (Show Off and delete regionid 0)
RET_CODE lib_subt_atsc_clear_osd(struct osd_device *subt_atsc_osd_dev)
{
    RET_CODE ret = SUCCESS;
//    return ret;
    do{
        //if(!g_subt_atsc_osd_present)
        //    break;
        
        ret = OSDDrv_ShowOnOff((HANDLE)subt_atsc_osd_dev,OSDDRV_OFF);
        if(SUCCESS != ret)
            break;
        
        ret = OSDDrv_DeleteRegion((HANDLE)subt_atsc_osd_dev,0);  
        if(SUCCESS != ret)
            break;
        osd_status = 0;
        osd_region_deleted = TRUE;
    }while(0);
    return ret;
}


//Fill color specified to rectangle specified
void lib_subt_atsc_display(struct OSDRect *rect,ATSC_subt_bmp_header *bmp_header,UINT16 color)
{
    struct osd_device *subt_atsc_osd_dev= lib_subt_atsc_get_osd_handle();	
//    UINT8* subt_atsc_vscreen =g_subt_config_par.g_ps_buf_addr;
     //OSDDrv_RegionFill((HANDLE)subt_atsc_osd_dev,0,rect,color);
#if 1 
	UINT8* subt_atsc_vscreen =g_subt_config_par.g_ps_buf_addr;
     do{
         int x,y;
         if(rect->uLeft + rect->uWidth >= g_subt_atsc_rect.uLeft+ g_subt_atsc_rect.uWidth)
             SUBT_ATSC_OSD_PRINTF("width error\n");
         if(rect->uTop+ rect->uHeight>= g_subt_atsc_rect.uTop+g_subt_atsc_rect.uHeight)
             SUBT_ATSC_OSD_PRINTF("height error\n");
		 
#ifdef SHOW_BY_CPU	//vicky20110322         
        OSDDrv_RegionFill((HANDLE)subt_atsc_osd_dev,0,rect,color);
#else
         for(y = rect->uTop; y<rect->uTop + rect->uHeight; ++y)
         {
             for(x = rect->uLeft; x<rect->uLeft + rect->uWidth; ++x)
                 *(subt_atsc_vscreen+x+y*g_subt_atsc_rect.uWidth) = color;
         }
#endif	 		 
     }while(0);
#endif
    return;
}

extern BOOL g_lib_subt_atsc_clean_osd;
// Display subt
void lib_subt_atsc_show_screen()
{
	UINT8* subt_atsc_vscreen =g_subt_config_par.g_ps_buf_addr;
    struct OSDRect rect,rect1;
	UINT16 amendHeightReal;
    rect.uTop = 0;
    rect.uLeft = 0;
    rect.uHeight = g_subt_atsc_rect.uHeight;
    rect.uWidth = g_subt_atsc_rect.uWidth;
	amendHeightReal = globeHeightReal+0xf;
    if(bCenter)
    {
		rect1.uTop = 0;
    	rect1.uLeft =(g_subt_atsc_rect.uWidth-globeWidthReal)>>1;
    	rect1.uHeight = amendHeightReal;//g_subt_atsc_rect.uHeight;
    	rect1.uWidth = globeWidthReal+0xf;
        #if 0
		if(FALSE == user_force)
		{
		   if(rect1.uTop+amendHeightReal>=g_subt_atsc_rect.uHeight)
		   	    rect1.uTop = g_subt_atsc_rect.uHeight-amendHeightReal;
		}
		else
		{ 
		   if(rect1.uTop+amendHeightReal>=g_subt_atsc_rect.uHeight)
		   {
		   	   rect1.uHeight = g_subt_atsc_rect.uHeight -rect1.uTop;
			   if(rect1.uHeight<=0)
			   	rect1.uHeight = 0;
		   }
		}
        #endif
    }
	else
	{
	rect1.uTop = 0;
    rect1.uLeft = 0;
    rect1.uHeight = g_subt_atsc_rect.uHeight;
    rect1.uWidth = g_subt_atsc_rect.uWidth;
	}
    SUBT_ATSC_OSD_PRINTF("Subt_Area:L(%d),T(%d),W(%d),H(%d)\n",	g_subt_atsc_rect.uLeft,g_subt_atsc_rect.uTop,	g_subt_atsc_rect.uWidth,g_subt_atsc_rect.uHeight);	

    struct osd_device *subt_atsc_osd_dev= lib_subt_atsc_get_osd_handle();
#ifdef SHOW_BY_CPU	//vicky20110314	
    //OSDDrv_ShowOnOff((HANDLE)subt_atsc_osd_dev, OSDDRV_ON);
    OSDDrv_RegionShow((HANDLE)subt_atsc_osd_dev,0,TRUE);
#else
    OSDDrv_RegionWrite2((HANDLE)subt_atsc_osd_dev, 0, subt_atsc_vscreen, g_subt_atsc_rect.uWidth, g_subt_atsc_rect.uHeight,&rect, &rect1);
#endif
    return;
}
// get rectangle according to display standard
BOOL lib_subt_atsc_get_osd_rect(DISPLAY_STANDARD_TYPE type, struct OSDRect *rect)
{
    BOOL ret = FALSE;
    UINT16 h_limited = 0;
    UINT16 v_limited = 0;
    do{
        switch(type)
        {
            default:
                ret = FALSE;
                break;
            case TYPE_720_480_30:
                h_limited = 720;
                v_limited = 480;
//                libc_printf("1\n");
                break;
            case TYPE_720_576_25:
                h_limited = 720;
                v_limited = 576;
//                libc_printf("2\n");
                break;
            case TYPE_1280_720_60:
                h_limited = 1280;
                v_limited = 720;
//                libc_printf("3\n");
                break;
            case TYPE_1920_1080_60:
                h_limited = 1920;
                v_limited = 1080;
//                libc_printf("4\n");
                break;
        }
        
        if(rect->uTop >= v_limited || rect->uTop < 0 || rect->uHeight< 0 )
        {
            SDBBP();
            break;
        }
         if(rect->uLeft>= h_limited || rect->uLeft < 0 || rect->uWidth < 0 )
        {
            SDBBP();
            break;
        }

        if( (rect->uHeight + rect->uTop > v_limited) && (rect->uTop < v_limited))
        {
            SUBT_ATSC_OSD_PRINTF("height too large\n");
            rect->uTop = rect->uTop - (rect->uTop + rect->uHeight - v_limited);
        }
        
        if( (rect->uWidth+ rect->uLeft> h_limited) && (rect->uLeft< h_limited))
        {
            SUBT_ATSC_OSD_PRINTF("width too large %d %d %d %d\n",rect->uWidth,rect->uLeft,rect->uWidth+rect->uLeft,h_limited);
            rect->uLeft = rect->uLeft - (rect->uWidth+ rect->uLeft - h_limited)-32;
        }

//        rect->uLeft = (rect->uLeft - 0xf) & 0xfffffff0;
//        if(rect->uLeft < 0)
//            rect->uLeft = 0;
        if(bCenter)
		{   
            rect->uLeft = 0;
			rect->uTop = (rect->uTop - 0xf) & 0xfffffff0;
	        if(rect->uTop < 0)
	            rect->uTop = 0;
       		rect->uWidth = h_limited - rect->uLeft;
        	rect->uWidth = (rect->uWidth + 0xf) & 0xfffffff0;
        	rect->uHeight= v_limited - rect->uTop;
		}
		else
		{
	        rect->uLeft = (h_limited - rect->uWidth)>>1;
	        if(rect->uLeft < 0)
	            rect->uLeft = 0;
	        rect->uLeft = rect->uLeft & 0xfffffff0;

	        rect->uTop = (rect->uTop - 0xf) & 0xfffffff0;
	        if(rect->uTop < 0)
	            rect->uTop = 0;
	        rect->uWidth = h_limited - rect->uLeft;
	        rect->uWidth = (rect->uWidth + 0xf) & 0xfffffff0;

	        rect->uHeight= v_limited - rect->uTop;
		}
        if( (rect->uWidth+ rect->uLeft> h_limited) && (rect->uLeft< h_limited))
        {
            rect->uWidth = h_limited- rect->uLeft;
        }
        
        if( rect->uWidth+ rect->uLeft> h_limited)
        {
            break;
        }
        if(rect->uWidth < 0 || rect->uHeight < 0 )
        {
            break;
        }
        ret = TRUE;
    }while(0);
    
    return ret;
}

//Begin:change DC2 Subtitle color and position set of the stream:add by Colin
void lib_subt_atsc_hcenter_on_off(BOOL bOnOff)
{
     bCenter = bOnOff;
}
/*
void lib_subt_atsc_shift_y_set(INT32 nShiftY)
{
    shifty_dcii_subt = nShiftY;
}
*/
void lib_subt_atsc_force_shift_y_set(BOOL userForce,INT32 nShiftY)
{
    user_force = userForce;
    shifty_dcii_subt = nShiftY;
}

void lib_subt_atsc_color_exchange_on_off(BOOL bOnOff)
{
    bColorExchange = bOnOff;   
}

void lib_subt_atsc_color_exchange__color_char_set(UINT8 uY,UINT8 uCb,UINT8 uCr,UINT8 uK)
{
     charY = uY;
     charCb = uCb;
     charCr = uCr;
     charK = uK;	
}

void lib_subt_atsc_color_exchange__color_outline_set(UINT8 uY,UINT8 uCb,UINT8 uCr,UINT8 uK)
{
     outlineY = uY;
     outlineCb = uCb;
     outlineCr = uCr;
     outlineK = uK;	
}
//End:change DC2 Subtitle color and position set of the stream

// Set Pallette
RET_CODE lib_subt_atsc_osd_set_pallette(struct osd_device *subt_atsc_osd_dev,ATSC_subt_bmp_header *bmp_header)
{
    RET_CODE ret;
    do{
        //ret = OSDDrv_SetPallette((HANDLE)subt_atsc_osd_dev,subt_atsc_palette,256,OSDDRV_YCBCR);
        
        ret = OSDDrv_ModifyPallette((HANDLE)subt_atsc_osd_dev,ATSC_SUBT_CHAR_COLOR_INDEX,\
                                       bmp_header->char_color.Y_component*8, \
                                       bmp_header->char_color.Cb_component*8,\
                                       bmp_header->char_color.Cr_component*8,\
                                       bmp_header->char_color.opaque_enable?0xf:8);
        if(SUCCESS!= ret)
            break;
        ret = OSDDrv_ModifyPallette((HANDLE)subt_atsc_osd_dev,ATSC_SUBT_FRAME_COLOR_INDEX,\
                                       bmp_header->bmp_frame.frame_color.Y_component*8,\
                                       bmp_header->bmp_frame.frame_color.Cb_component*8,\
                                       bmp_header->bmp_frame.frame_color.Cr_component*8,\
                                       bmp_header->bmp_frame.frame_color.opaque_enable?0xf:8);
        if(SUCCESS!= ret)
            break;
        ret = OSDDrv_ModifyPallette((HANDLE)subt_atsc_osd_dev,ATSC_SUBT_OUTLINE_COLOR_INDEX,\
                                       bmp_header->bmp_outline.outline_color.Y_component*8,\
                                       bmp_header->bmp_outline.outline_color.Cb_component*8,\
                                       bmp_header->bmp_outline.outline_color.Cr_component*8,\
                                       bmp_header->bmp_outline.outline_color.opaque_enable?0xf:8);
        if(SUCCESS!= ret)
            break;
        ret = OSDDrv_ModifyPallette((HANDLE)subt_atsc_osd_dev,ATSC_SUBT_SHADOW_COLOR_INDEX,\
                                       bmp_header->bmp_drop_shadow.shadow_color.Y_component*8,\
                                       bmp_header->bmp_drop_shadow.shadow_color.Cb_component*8,\
                                       bmp_header->bmp_drop_shadow.shadow_color.Cr_component*8,\
                                       bmp_header->bmp_drop_shadow.shadow_color.opaque_enable?0xf:8);
        if(SUCCESS!= ret)
            break;
		if(bColorExchange)
		{  
		    ret = OSDDrv_ModifyPallette((HANDLE)subt_atsc_osd_dev,ATSC_SUBT_CHAR_COLOR_INDEX,charY, charCb, charCr,charK);
            ret = OSDDrv_ModifyPallette((HANDLE)subt_atsc_osd_dev,ATSC_SUBT_OUTLINE_COLOR_INDEX,outlineY, outlineCb, outlineCr,outlineK);  
		}
        //OSDDrv_RegionFill((HANDLE)subt_atsc_osd_dev,0,&rect,OSD_TRANSPARENT_COLOR);
    }while(0);
}

